package com.wmapp.domain;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import net.sf.json.JSONArray;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

import com.wmapp.language.Lang;
import com.wmapp.utils.SimpleStringUtils;

/**
 * Conference Reservation Domain.
 * 
 * @author dengl
 * 
 *         <h2>rec_type</h2>
 *         <p>
 *         This data will be set automatically through scheduler interface type
 *         of recurring encoded in string
 *         [type]_[count]_[day]_[count2]_[days]#[extra]
 *         </p>
 *         <ul>
 *         <li>type - type of repeating “day”,”week”,”week”,”month”,”year”</li>
 *         <li>count - how much intervals of “type” come between events</li>
 *         <li>count2 and day - used to define day of month ( first Monday,
 *         third Friday, etc )</li>
 *         <li>days - comma separated list of affected week days</li>
 *         <li>extra - this info is not necessary for calculation, but can be
 *         used to correct presentation of recurring details</li>
 *         </ul>
 *         <p>
 *         <h2>For example:</h2>
 *         <ul>
 *         <li>day_3___# - each three days with end date</li> 
 *         <li>day_2___#no - each two days with no end date </li>
 *         <li>month _2___#2 - each two month and ended after 2 occurrences  </li>
 *         <li>month_2_2_4_#2 - fourth Tuesday of each tow month and ended after 2 occurrences  </li>
 *         <li>week_2___1,5# - Monday and Friday of each second week with end date</li>
 *         </ul>
 *         </p>
 *         <h2>event_length<h2>
 *         <p>
 *         length of event in seconds ( in case of recurring event, end data
 *         shows the moment when recurring will be finished, so separate field
 *         is necessary to store actual length )
 *         </p>
 */
public class ConfReservation {
	private final static Log log=LogFactory.getLog(ConfReservation.class);
	
	private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
	// Recurring event information
	private String id;// recurring event id
	private String text;// recurring event description same as conference name
	private String start_date;// recurring start date
	private String end_date;// recurring end date
	private String rec_type;// recurring type
	private String event_length;// length of event in seconds

	// Conference Information
	private String owner;// Conference Reservation owner
	private String group;// limit which group use this conference,if empty,every
							// user can use this conference
	private String modifyTime;
	private String number;
	private String name;
	private String topic;// description
	private String password;
	private String chairpassword;
	private String bandwidth;
	private String maxAudioPorts;
	private String maxVideoPorts;
	private String reservedAudioPorts;// boolean
	private String reservedVideoPorts;// boolean
	private String encryptEnabled;// boolean
	private String encryptForced;// boolean
	private String callInType;// {"list","none","all","registered" }
	private String muteOnJoin;
	private String audioFormats;
	private String h263cif4Enabled;// boolean
	private String h264Enabled;// boolean
	private String h264Definition;
	private String h239Bandwidth;
	private String h239Enabled;// boolean
	private String h239Codec;
	private String textPosition;
	private String textFont;
	private String textColor;
	private String textBgEnabled;
	private String textBgColor;
    private String textDisplayTime;
	private String broadcastEnabled;
	private String broadcastBandwidth;
	private String broadcastPassword;
	private String broadcastNumLimit;
	private List<ConfParticipant> participants = new ArrayList<ConfParticipant>(); // actually
																					// participants
	
	private String participantsJSON;//help property,json string
	private String encrypt;//help property
	
	private String emailNotify;//"true" or "false"
	
	//For schedule representation
	public static final String[] LIST_FIELDS={"id","text","start_date","end_date","rec_type","event_length","number","topic"};
	public static final String[] ADD_FIELDS={"id","text","start_date","end_date","rec_type","event_length",
		"owner","group","modifyTime","number","name","topic","password","chairpassword","bandwidth",
		"maxAudioPorts","maxVideoPorts","reservedAudioPorts","reservedVideoPorts","encryptEnabled","encryptForced","callInType","muteOnJoin","audioFormats",
		"h263cif4Enabled","h264Enabled","h264Definition","h239Bandwidth","h239Enabled","h239Codec","textPosition","textFont","textColor",
		"textBgEnabled","textBgColor","textDisplayTime",
        "broadcastEnabled","broadcastBandwidth","broadcastPassword","broadcastNumLimit"};
	public static final String[] UPDATE_FIELDS={"id","text","start_date","end_date","rec_type","event_length",
		"owner","group","modifyTime","number","name","topic","password","chairpassword","bandwidth",
		"maxAudioPorts","maxVideoPorts","reservedAudioPorts","reservedVideoPorts","encryptEnabled","encryptForced","callInType","muteOnJoin","audioFormats",
		"h263cif4Enabled","h264Enabled","h264Definition","h239Bandwidth","h239Enabled","h239Codec","textPosition","textFont","textColor",
		"textBgEnabled","textBgColor","textDisplayTime",
        "broadcastEnabled","broadcastBandwidth","broadcastPassword","broadcastNumLimit"};
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getText() {
		return name;
	}

	public String getStart_date() {
		return start_date;
	}

	public void setStart_date(String start_date) {
		this.start_date = start_date;
	}

	public String getEnd_date() {
		return end_date;
	}

	public void setEnd_date(String end_date) {
		this.end_date = end_date;
	}

	public String getRec_type() {
		return rec_type;
	}

	public void setRec_type(String rec_type) {
		this.rec_type = rec_type;
	}

	public String getEvent_length() {
		return event_length;
	}

	public void setEvent_length(String event_length) {
		this.event_length = event_length;
	}

	public String getOwner() {
		return owner;
	}

	public void setOwner(String owner) {
		this.owner = owner;
	}

	public String getGroup() {
		return group;
	}

	public void setGroup(String group) {
		this.group = group;
	}

	public String getModifyTime() {
		return modifyTime;
	}

	public void setModifyTime(String modifyTime) {
		this.modifyTime = modifyTime;
	}
	
	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTopic() {
		return topic;
	}

	public void setTopic(String topic) {
		this.topic = topic;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getChairpassword() {
		return chairpassword;
	}

	public void setChairpassword(String chairpassword) {
		this.chairpassword = chairpassword;
	}

	public String getBandwidth() {
		return bandwidth;
	}

	public void setBandwidth(String bandwidth) {
		this.bandwidth = bandwidth;
	}

	public String getMaxAudioPorts() {
		return maxAudioPorts;
	}

	public void setMaxAudioPorts(String maxAudioPorts) {
		this.maxAudioPorts = maxAudioPorts;
	}

	public String getMaxVideoPorts() {
		return maxVideoPorts;
	}

	public void setMaxVideoPorts(String maxVideoPorts) {
		this.maxVideoPorts = maxVideoPorts;
	}

	public String getReservedAudioPorts() {
		return reservedAudioPorts;
	}

	public void setReservedAudioPorts(String reservedAudioPorts) {
		this.reservedAudioPorts = reservedAudioPorts;
	}

	public String getReservedVideoPorts() {
		return reservedVideoPorts;
	}

	public void setReservedVideoPorts(String reservedVideoPorts) {
		this.reservedVideoPorts = reservedVideoPorts;
	}

	public String getEncryptEnabled() {
		return encryptEnabled;
	}

	public void setEncryptEnabled(String encryptEnabled) {
		if(encryptEnabled!=null&&encryptEnabled.equals("true")){
			this.encrypt="enable";
		}
		if(encryptEnabled!=null&&encryptEnabled.equals("false")){
			this.encrypt="disable";
		}
		this.encryptEnabled = encryptEnabled;
	}

	public String getEncryptForced() {
		return encryptForced;
	}

	public void setEncryptForced(String encryptForced) {
		if(encryptForced!=null&&encryptForced.equals("true")){
			this.encrypt="forced";
		}
		this.encryptForced = encryptForced;
	}

	public String getCallInType() {
		return callInType;
	}

	public void setCallInType(String callInType) {
		this.callInType = callInType;
	}

	public String getMuteOnJoin() {
		return muteOnJoin;
	}

	public void setMuteOnJoin(String muteOnJoin) {
		this.muteOnJoin = muteOnJoin;
	}

	public String getAudioFormats() {
		return audioFormats;
	}

	public void setAudioFormats(String audioFormats) {
		this.audioFormats = audioFormats;
	}

	public String getH263cif4Enabled() {
		return h263cif4Enabled;
	}

	public void setH263cif4Enabled(String h263cif4Enabled) {
		this.h263cif4Enabled = h263cif4Enabled;
	}

	public String getH264Enabled() {
		return h264Enabled;
	}

	public void setH264Enabled(String h264Enabled) {
		this.h264Enabled = h264Enabled;
	}

	public String getH264Definition() {
		return h264Definition;
	}

	public void setH264Definition(String h264Definition) {
		this.h264Definition = h264Definition;
	}

	public String getH239Bandwidth() {
		return h239Bandwidth;
	}

	public void setH239Bandwidth(String h239Bandwidth) {
		this.h239Bandwidth = h239Bandwidth;
	}

	public String getH239Enabled() {
		return h239Enabled;
	}

	public void setH239Enabled(String h239Enabled) {
		this.h239Enabled = h239Enabled;
	}

	public String getH239Codec() {
		return h239Codec;
	}

	public void setH239Codec(String h239Codec) {
		this.h239Codec = h239Codec;
	}

	public String getTextPosition() {
		return textPosition;
	}

	public void setTextPosition(String textPosition) {
		this.textPosition = textPosition;
	}

	public String getTextFont() {
		return textFont;
	}

	public void setTextFont(String textFont) {
		this.textFont = textFont;
	}

	public String getTextColor() {
		return textColor;
	}

	public void setTextColor(String textColor) {
		this.textColor = textColor;
	}

	public String getTextBgEnabled() {
		return textBgEnabled;
	}

	public void setTextBgEnabled(String textBgEnabled) {
		this.textBgEnabled = textBgEnabled;
	}

	public String getTextBgColor() {
		return textBgColor;
	}

	public void setTextBgColor(String textBgColor) {
		this.textBgColor = textBgColor;
	}

     public String getTextDisplayTime() {
		return textDisplayTime;
	}

	public void setTextDisplayTime(String textDisplayTime) {
		this.textDisplayTime = textDisplayTime;
	}
	public String getBroadcastEnabled() {
		return broadcastEnabled;
	}

	public void setBroadcastEnabled(String broadcastEnabled) {
		this.broadcastEnabled = broadcastEnabled;
	}

	public String getBroadcastBandwidth() {
		return broadcastBandwidth;
	}

	public void setBroadcastBandwidth(String broadcastBandwidth) {
		this.broadcastBandwidth = broadcastBandwidth;
	}

	public String getBroadcastPassword() {
		return broadcastPassword;
	}

	public void setBroadcastPassword(String broadcastPassword) {
		this.broadcastPassword = broadcastPassword;
	}

	public String getBroadcastNumLimit() {
		return broadcastNumLimit;
	}

	public void setBroadcastNumLimit(String broadcastNumLimit) {
		this.broadcastNumLimit = broadcastNumLimit;
	}

	public List<ConfParticipant> getParticipants() {
		return participants;
	}

	public void setParticipants(List<ConfParticipant> participants) {
		this.participants = participants;
		
		if(participants!=null&&!participants.isEmpty()){
			this.participantsJSON=JSONArray.fromObject(participants).toString();
		}
	}
	
	public void setEncrypt(String encrypt) {
		if(encrypt!=null&&encrypt.equals("disable")){
			this.encryptEnabled="false";
		}
		if(encrypt!=null&&encrypt.equals("enable")){
			this.encryptEnabled="true";
		}
		if(encrypt!=null&&encrypt.equals("forced")){
			this.encryptForced="true";
		}
		this.encrypt = encrypt;
	}
	
	public String getEncrypt() {
		return encrypt;
	}
	
	public String getParticipantsJSON() {
		return participantsJSON;
	}

	public void setParticipantsJSON(String participantsJSON) {
		this.participantsJSON = participantsJSON;
		
		if(this.participantsJSON!=null){
			JSONArray jArray=JSONArray.fromObject(this.participantsJSON);
			this.participants=(List)jArray.toCollection(jArray,ConfParticipant.class);
		}
	}

	public String getEmailNotify() {
		return emailNotify;
	}

	public void setEmailNotify(String emailNotify) {
		this.emailNotify = emailNotify;
	}
	
	/**
	 * Build email subject
	 * @param lang i18n class
	 * @return
	 */
	public String getEmailSubject(Lang lang){
		return SimpleStringUtils.join(name,"(",number,")");
	}
	/**
	 * Build email Body
	 * @param lang i18n class
	 * @return
	 */
	public String getEmailBody(Lang lang){
		StringBuffer buffer=new StringBuffer();
		//Start Date
		buffer.append(lang.getMsg("conf.reservation.starttime"));
		buffer.append(":");
		buffer.append(start_date);
		buffer.append("\n");
		//Conference Length
		buffer.append(lang.getMsg("conf.reservation.length"));
		buffer.append(":");
		buffer.append(StringUtils.hasText(event_length)?Integer.valueOf(event_length)/60:getConfLength());//minutes
		buffer.append(" ");
		buffer.append(lang.getMsg("conf.reservation.minute"));
		buffer.append("\n");
		//Conference Type
		buffer.append(lang.getMsg("conf.reservation.type"));
		buffer.append(":");
		buffer.append(getConfTypeDesc(lang));
		buffer.append("\n");
		//Topic
		buffer.append(lang.getMsg("conf.reservation.topic"));
		buffer.append(":");
		buffer.append(topic);
		buffer.append("\n");
		
		return buffer.toString();
	}
	
	private int getConfLength(){
		if (StringUtils.hasText(event_length)) {
			return Integer.valueOf(event_length) / 60;
		} else {
			try {
				Date sDate = format.parse(start_date);
				Date eDate = format.parse(end_date);
				return (int) ((eDate.getTime() - sDate.getTime()) / 1000 / 60);
			} catch (ParseException e) {
				log.error(e.getMessage(), e);
			}
		}

		return 0;
	}
	
	private String getConfTypeDesc(Lang lang){
		StringBuffer buffer=new StringBuffer();
		if(rec_type!=null&&!rec_type.equals("")){
			String extra=rec_type.split("#",2)[1];
			String[] params=rec_type.split("#",2)[0].split("_",5);
			String type=params[0];
			String count=params[1];
			String day=params[2];
			String count2=params[3];
			String days=params[4];
			
			buffer.append(lang.getMsg("conf.reservation.every"));
			buffer.append(" ");
			buffer.append(count);
			if(type.equals("day")){
				buffer.append(" ");
				buffer.append(lang.getMsg("conf.reservation.day"));
			}else if(type.equals("week")){
				buffer.append(" ");
				buffer.append(lang.getMsg("conf.reservation.week"));
				buffer.append(" ");
				buffer.append(days);
			}else if(type.equals("month")){
				buffer.append(" ");
				buffer.append(lang.getMsg("conf.reservation.month"));
				if(!day.equals("")&&!count2.equals("")){
					buffer.append(" ");
					buffer.append(lang.getMsg("conf.reservation.on"));
					buffer.append(" ");
					buffer.append(count2);
					buffer.append(" ");
					buffer.append(parseDay(Integer.valueOf(day),lang));
				}
			}
			
			buffer.append(".");
			buffer.append(parseExtra(extra,lang));
		}else{
			buffer.append(lang.getMsg("conf.reservation.norepeat"));
		}
		return buffer.toString();
	}
	
	private String parseExtra(String extra,Lang lang){
		if(extra!=null){
			if(extra.equals("no")){
				return lang.getMsg("conf.reservation.noend");
			}else if(Pattern.compile("0|([1-9][0-9]*)").matcher(extra).matches()){
				return SimpleStringUtils.join(lang.getMsg("conf.reservation.after")," ",extra," ",lang.getMsg("conf.reservation.times")," ",lang.getMsg("conf.reservation.end"));
			}else{
				return SimpleStringUtils.join(lang.getMsg("conf.reservation.after")," ",this.end_date," ",lang.getMsg("conf.reservation.end"));
			}
		}
		
		return "";
	}
	
	private String parseDay(int day,Lang lang){
		String days=lang.getMsg("conf.reservation.days");
		if(StringUtils.hasText(days)){
			String[] daysArray=days.split(",");
			return daysArray[day-1];
		}else{
			return String.valueOf(day);
		}
	}
}
